package com.navinfo.platform.trip.analysis.service;

import com.navinfo.platform.trip.common.util.ClassUtils;
import com.navinfo.platform.trip.common.annotation.SystemType;
import com.navinfo.platform.trip.common.enums.SystemTypeEnum;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.Map;
import java.util.Optional;
import java.util.TreeMap;
import java.util.concurrent.ConcurrentHashMap;

/**
 * Service工厂类
 * @author: web
 * @data: 2020-04-08
 **/
@SuppressWarnings("unchecked")
public class ServiceFactory {
    private static final Logger logger = LoggerFactory.getLogger(ServiceFactory.class);
    /**
     * 各种系统运行类型的下接口的不同实现Map<br/>
     * key为：运行环境 + "**" + 接口名
     * value为：实现类的Class
     */
    private static final Map<String, Class> serviceMap = new TreeMap<>();

    /**
     * 接口实现类的实例缓存
     */
    private static final Map<String, Object> serviceInstance = new ConcurrentHashMap<>();

    static{
        synchronized (serviceMap){
            //扫描工程包下添加了RunningType注解的class，注册系统运行时各接口的类实现
            ClassUtils.getClasses("com.navinfo.platform.trip.analysis.service.impl")
                .forEach(clazz -> Optional.ofNullable(clazz.getAnnotation(SystemType.class)).ifPresent(
                        systemType -> serviceMap.put(systemType.value().getType()+ "**"+ systemType.interfaceClass().getSimpleName(), clazz)));

            StringBuilder sb = new StringBuilder();
            serviceMap.forEach((key, value) -> sb.append(key).append("-->").append(value.getName()).append("\n"));

            logger.info("系统服务工厂初始化完毕，不同运行环境下的接口实现如下：\n{}", sb.toString());
        }
    }

    /**
     * 创建不同系统对应接口的实现类（单例）
     * @param systemTypeEnum 系统类型
     * @param clazz 接口class
     * @param <T> 返回类型
     * @return 接口的实现类
     */
    public static <T> T singleServiceImpl(SystemTypeEnum systemTypeEnum, Class<T> clazz)  {
        if(null == systemTypeEnum){
            throw new RuntimeException("请传入系统类型，1东风，2青汽，3一汽");
        }

        String serviceKey = systemTypeEnum.getType() + "**" + clazz.getSimpleName();
        return (T)serviceInstance.computeIfAbsent(serviceKey, key -> createServiceImpl(systemTypeEnum, clazz));
    }

    /**
     * 创建不同系统对应接口的实现类（多实例）
     * @param systemTypeEnum 系统类型
     * @param clazz 接口class
     * @param <T> 返回类型
     * @return 接口的实现类
     */
    public static <T> T createServiceImpl(SystemTypeEnum systemTypeEnum, Class<T> clazz)  {
        if(null == systemTypeEnum){
            throw new RuntimeException("请传入系统运行类型，1东风，2青汽，3一汽");
        }
        Class aClass;
        synchronized (serviceMap){
            aClass = serviceMap.get(systemTypeEnum.getType() + "**" + clazz.getSimpleName());
        }
        logger.info("创建{}的实现类{}", clazz, aClass);
        try {
            return  (T) aClass.newInstance();
        } catch (Exception e) {
            logger.error("创建{}的实现类{}失败",clazz, aClass, e);
        }

        return null;
    }

}
